﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using CacheProvider;
using Microsoft.Practices.Composite.Presentation.Events;
using CacheProviderEntities;
using System.Configuration;

namespace DemoWpfApplication
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class CacheTestWindow : Window
    {
        public CacheTestWindow()
        {
            InitializeComponent();
        }


        private void ButtonGetProductDetails_Click(object sender, RoutedEventArgs e)
        {
            var products = GetProducts();

            const string key = "SqlDependencyCache";
            var data = CacheBroker.Get<List<Product>>(key);
            if (data == null)
            {
                Label1.Content = "Reading From Database";

                data = GetProducts();
                var dependencyInfo = new DependencyInfo(CacheDependencyTypes.SQLDependency)
                {
                    DBName = "AdventureWorks",
                    DBConnectionString = GetConnectionString(),
                    IsSQLSelectQueryBased = true
                };

                dependencyInfo.SelectQueries.Add(GetSQL());

                CacheBroker.Put(key, data, string.Empty, TimeSpan.Zero, null, dependencyInfo, HydrateCache, key, ThreadOption.UIThread, true);

                Label1.Content = "Done!Read From Database";
            }
            else
            {
                Label1.Content = "Done! Read From Cache";
            }

            ListViewProducts.ItemsSource = products;
        }


        public List<Product> GetProductList()
        {

            const string key = "SqlDependencyCache";

            var products = CacheBroker.Get<List<Product>>(key);

            if (products == null)
            {
                products = GetProducts();

                CacheBroker.Put(key, products);
            }

            return products;
        }


        private void HydrateCache(object state)
        {
            Label1.Content = "Dependency Changed! Updating Grid";

            this.Cursor = Cursors.Wait;

            var key = state as string;

            Debug.Assert(!string.IsNullOrEmpty(key));

            var data = GetProducts();
            var dependencyInfo = new DependencyInfo(CacheDependencyTypes.SQLDependency)
            {
                DBName = "AdventureWorks",
                DBConnectionString = GetConnectionString(),
                IsSQLSelectQueryBased = true
            };

            dependencyInfo.SelectQueries.Add(GetSQL());

            CacheBroker.Put<object>(key, data, string.Empty, TimeSpan.Zero, null, dependencyInfo, HydrateCache, key, ThreadOption.UIThread, true);

            ListViewProducts.ItemsSource = data;

            Label1.Content = "Grid Updated at " + DateTime.Now;

            this.Cursor = Cursors.Arrow;
        }

        private static List<Product> GetProducts()
        {
            var products = new List<Product>();
            using (var connection = new SqlConnection(GetConnectionString()))
            using (var sqlCommand = new SqlCommand(GetSQL(), connection))
            {
                connection.Open();
                IDataReader reader = sqlCommand.ExecuteReader();
                if (reader != null)
                {
                    int productIdIndex = reader.GetOrdinal("ProductId");
                    int productNameIndex = reader.GetOrdinal("ProductName");
                    int productLocationIndex = reader.GetOrdinal("Location");
                    int productQuantityIndex = reader.GetOrdinal("Quantity");
                    while (reader.Read())
                    {
                        var product = new Product()
                                          {
                                              ProductId = reader.GetInt32(productIdIndex),
                                              Name = reader.GetString(productNameIndex),
                                              Location = reader.GetString(productLocationIndex),
                                              Quantity = reader.GetInt16(productQuantityIndex)
                                          };
                        products.Add(product);
                    }
                }
            }

            return products;
        }

        private static string GetConnectionString()
        {
            /*if (Environment.MachineName.Equals("IN8202039D"))
                return @"Data Source=SRVBLRCAF01\MSBLRTCTD01;Integrated Security=true;" +
                  "Initial Catalog=AdventureWorks;";

            return @"Data Source=RAHUL-PC\SQL2008EXPRESS;Integrated Security=true;" +
              "Initial Catalog=AdventureWorks;";*/
            return ConfigurationManager.ConnectionStrings["AdventureWorks"].ToString();
        }

        private static string GetSQL()
        {
            return "SELECT Production.Product.ProductID AS ProductId, " +
            "Production.Product.Name AS ProductName, " +
            "Production.Location.Name AS Location, " +
            "Production.ProductInventory.Quantity AS Quantity " +
            "FROM Production.Product INNER JOIN " +
            "Production.ProductInventory " +
            "ON Production.Product.ProductID = " +
            "Production.ProductInventory.ProductID " +
            "INNER JOIN Production.Location " +
            "ON Production.ProductInventory.LocationID = " +
            "Production.Location.LocationID " +
            "WHERE ( Production.ProductInventory.Quantity <= 100 ) " +
            "ORDER BY Production.ProductInventory.Quantity, " +
            "Production.Product.Name;";
        }
    }

    //public class Product

    public class Product
    {
        public int ProductId { get; set; }
        public string Name { get; set; }
        public string Location { get; set; }
        public int Quantity { get; set; }

        public override bool Equals(object obj)
        {
            var other = obj as Product;
            if (other == null)
                return false;
            if (!obj.GetType().Equals(this))
                return false;
            if (other == this)
                return true;
            if (ReferenceEquals(this, other))
                return true;
            if (this.ProductId == other.ProductId
                && this.Name.Equals(other.Name)
                && this.Location.Equals(other.Location)
                && this.Quantity.Equals(other.Quantity))
                return true;
            else
                return false;
        }

        public override int GetHashCode()
        {
            return (ProductId +
                Name +
                Location +
                Quantity).GetHashCode();
        }
    }
}
